home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 4 / FM Towns Free Software Collection 4 - Disc 1.iso / t_os / who / srchword.c next >
C/C++ Source or Header  |  1991-10-18  |  4KB  |  158 lines

  1. /* srchword  writen by GOOSE 1991.8.9
  2. ** 機能:
  3. **   1ファイルに対し,複数のキーワードで検索し,キーワードを含む行を出力する。
  4. ** 呼び出し形式:
  5. **   srchword  [-all] 検索対象ファイル名
  6. **      -allが指定されていると,必ずファイルの最後まで検索する。
  7. **      -allがない場合は,未一致のキーワードがなくなった時点で処理を終える。
  8. ** その他:
  9. **   キーワードは標準入力から与える。従って,ファイルから入力する場合は,
  10. **       srchword  検索対象ファイル名 < キーワードファイル名
  11. **   のようにリダイレクトする。
  12. **   なお,データ1行に対する文字列比較は,キーワードの1つが一致した時点で打ち
  13. **   切ることに注意。
  14. **   各キーワードは,次の何れかで区切ること。
  15. **       ・1つ以上の空白(半角,全角) or
  16. **       ・1つ以上の水平タブ or
  17. **       ・改行 or 終端文字
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23.  
  24. #define W0  (ONE_WORD *)0
  25. #define ON  1
  26. #define OFF 0
  27.  
  28. typedef struct ONE_WORD {                   /* キーワードリストの構造体 */
  29.     struct ONE_WORD *next;
  30.     short           find;                   /* 一致行があったらON */
  31.     short           len;
  32.     char            word[1];                /* GCCなら要素0でもいいのに・・*/
  33. } ONE_WORD;
  34.  
  35. /********** skipblank **********/
  36. /* 文字列sのi番目以降の最初の空白(全角,半角,水平タブ)以外のオフセットを返す */
  37. short skipblank(short *i, char *s)
  38. {
  39.     for ( ;*(s+*i)!='\n' && *(s+*i)!='\0' ; (*i)++) {
  40.         if (*(s+*i)!=' ' && *(s+*i)!='\t' && memcmp(s+*i," ",2)!=0)
  41.             break;
  42.         if (memcmp(s+*i," ",2) == 0) (*i)++;
  43.     }
  44.     if ( *(s+*i) == '\n' ) *(s+*i) = '\0';
  45.     return(*i);
  46. }
  47. /********** skipchar **********/
  48. /* 文字列sのi番目以降の次の文字のオフセットを返す.
  49. **    ・最初の空白(1byte,2byte),または
  50. **    ・水平タブまたは
  51. **    ・最初の指定された文字
  52. **    ALL文字列なら行末('\0')のオフセットを返す.
  53. */
  54. short skipchar(short *i, char *s, char *c)
  55. {
  56.     for ( ;*(s+*i)!='\n' && *(s+*i)!='\0' ; (*i)++) {
  57.         if (*(s+*i)==' ' || *(s+*i)=='\t' ||
  58.             *(s+*i)==*c||memcmp(s+*i," ",2)==0)
  59.             break;
  60.     }
  61.     if ( *(s+*i) == '\n' ) *(s+*i) = '\0';
  62.     return(*i);
  63. }
  64. /********** getoneword **********/
  65. /* 文字列sのi番目以降から1単語を切り出し,ONE_WORD構造体にセットして返す */
  66. ONE_WORD *getoneword(short *keyno,short *i, char *s)
  67. {
  68.     short    top,len;
  69.     ONE_WORD *ans;
  70.     
  71.     top = skipblank(i, s);             /* 先頭の空白を読み飛ばす */
  72.     if (*(s+top) == '\0') return(W0);  /* レコードの終わりなら戻る */
  73.     len = skipchar(i,s,",")-top;
  74.     if ((ans=(ONE_WORD *)malloc(sizeof(ONE_WORD)+len)) == W0) {
  75.         fprintf(stderr,"memory not enough!\n");
  76.         exit(1);
  77.     }
  78.     ans->next = W0;
  79.     ans->find = OFF;
  80.     ans->len = len;
  81.     (*keyno)++;
  82.     memcpy(ans->word, s+top, len);
  83.     *(ans->word+len) = '\0';
  84.     return(ans);
  85. }
  86.  
  87.  
  88. /********** main(srchword) **********/
  89. int main(argc, argv)
  90. int  argc;
  91. char *argv[];
  92. {
  93.     short    pos,reccount,len,keyno,all;
  94.     FILE     *fp;
  95.     ONE_WORD *topp,*wp;
  96.     char     indata[256],buf[256],*file;
  97.     
  98.     all = OFF;
  99.     topp = W0;
  100.     keyno = 0;
  101.     if (argc != 2 && argc!=3) {
  102.         fprintf(stderr,"usage: srchword [-all] filename < keyword_filename\n");
  103.         goto eend;
  104.     }
  105.     if (argc == 2)
  106.         file = argv[1];
  107.     else {
  108.         if (strcmp(argv[1],"-all") != 0) {
  109.             fprintf(stderr,"usage: srchword [-all] filename < keyword_filename\n");
  110.             goto eend;
  111.         }
  112.         all = ON;
  113.         file = argv[2];
  114.     }
  115.     
  116.     /* キーワードを読み込んでメモリ上に展開する */
  117.     for (wp=(ONE_WORD *)&topp,pos=0; gets(indata)!=NULL ; pos=0)
  118.         for (; (wp->next=getoneword(&keyno,&pos,indata))!=W0; wp=wp->next);
  119.     
  120.     /* 検索対象ファイルをオープン */
  121.     if ((fp=fopen(file,"r")) == NULL) {
  122.         fprintf(stderr, "file open error!\n");
  123.         goto eend;
  124.     }
  125.     
  126.     /* 検索対象ファイルのレコードがある間繰り返し */
  127.     for (reccount=1,pos=0; fgets(indata,256,fp)!=NULL; reccount++,pos=0) {
  128.         for (skipblank(&pos,indata); indata[pos]!='\0'; pos++) {
  129.             len = strlen(indata+pos);
  130.             /* 切り出した1wordと全キーワードを比較 */
  131.             for (wp=topp; wp!=W0; wp=wp->next) {
  132.                 if (len>=wp->len && memcmp(indata+pos,wp->word,wp->len)==0) {
  133.                         printf("%d: %s",reccount,indata);
  134.                         if (!all && wp->find == OFF) {
  135.                             keyno--;
  136.                             wp->find = ON;
  137.                             if (keyno == 0) goto srchend;
  138.                         }
  139.                         goto nextrec;
  140.                 }
  141.             }
  142.         }
  143. nextrec:;
  144.     }
  145.     
  146.     /* 後処理 */
  147. srchend:;
  148.     fclose(fp);
  149.     for (wp=topp; wp!=W0; wp=topp) {
  150.         topp = wp->next;
  151.         free(wp);
  152.     }
  153.     exit(0);
  154.     
  155. eend:
  156.     exit(1);
  157. }
  158.